#include <QStyleFactory>
#include <QSettings>
#include <QMessageBox>
#include <QCloseEvent>
#include <QJsonObject>
#include <QJsonDocument>
#include <QAction>
#include "LogModule.h"
#include "csyncbaseth.h"
#include "commgwmgr.h"
#include "cpublicdata.h"
#include "cclientdata.h"
#include "cglobal.h"
#include "clogoper.h"
#include "cclientstate.h"
#include "cclientpointmng.h"
#include "csysconfig.h"
#include "caboutdlg.h"
#include "cclientcfgdlg.h"
#include "ctag.h"
#include "ctagmobitordlg.h"
#include "cdrvsyncbasecfg.h"
#include "cepollservermgr.h"

CommGWMgr::CommGWMgr(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    m_pLogModule = nullptr;
    m_pTreeModel = nullptr;
    m_pSyncBaseTh = nullptr;
    m_pTcpServer = nullptr;
    initUi();           //初始化界面
    initConnect();      //初始化槽函数连接
    loadData();         //初始化ini配置文件,并初始化全局数据类,树节点搭建
    initSyncBase();     //初始化syncbase
    initTcpServer();    //启动TCP服务端
    startUpJudge();     //判断启动状态
    m_pTimer = new QTimer();
    connect(m_pTimer, &QTimer::timeout, this, &CommGWMgr::slotDataFlush);
    m_pTimer->start(1000);
}

CommGWMgr::~CommGWMgr()
{
    if(m_pTimer!=nullptr)
    {
        m_pTimer->stop();
        m_pTimer->deleteLater();
        m_pTimer=nullptr;
    }
    if(m_pSyncBaseTh!=nullptr)
    {
        m_pSyncBaseTh->threadStop();
        m_pSyncBaseTh->deleteLater();
        m_pSyncBaseTh=nullptr;
    }
    if(m_pTcpServer!=nullptr)
    {
        delete m_pTcpServer;
        m_pTcpServer=nullptr;
    }
}

void CommGWMgr::closeEvent(QCloseEvent *event)
{
    int ret = QMessageBox::information(this, A2T("提示"), A2T("是否确认退出?"), QMessageBox::Yes, QMessageBox::No);
    if (ret == QMessageBox::No)
    {
        event->ignore();
        return;
    }

    event->accept();
}

void CommGWMgr::initUi()
{
    //加载软件图标
    this->setWindowIcon(QIcon(":/icon/myapp.png"));
    //默认最大化
    this->showMaximized();
    this->setWindowTitle(QString::fromLocal8Bit("采集管理程序"));
    //QAction部分
    ui.actionLog->setChecked(true);
    ui.actionTool->setChecked(true);
    ui.actionProject->setChecked(true);

    //QTreeView部分
    m_pTreeModel = new QStandardItemModel();
    ui.treeView->setModel(m_pTreeModel);
    ui.treeView->setStyle(QStyleFactory::create("windows"));
    ui.treeView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui.treeView->setFrameShape(QFrame::NoFrame);
    ui.treeView->header()->hide();
    ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
    ui.treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui.treeView->setFocusPolicy(Qt::NoFocus);
    ui.treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    //TabWidget部分
    //设置tabWidget显示关闭按钮
    ui.tabWidget->setTabsClosable(true);
    ui.tabWidget->setContextMenuPolicy(Qt::CustomContextMenu);

    //日志部分
    m_pLogModule = new LogModule(A2T("采集管理程序"),"",this);
    CLogOper::instance().setLogModule(m_pLogModule);
    ui.gridLayoutLog->addWidget(m_pLogModule);
    ui.gridLayoutLog->setMargin(1);

    ui.dockWidgetLog->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
    ui.dockWidgetPro->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);

    ui.actionUserManual->setVisible(false);
}

void CommGWMgr::initConnect()
{
    connect(ui.tabWidget, &QTabWidget::tabCloseRequested, this, &CommGWMgr::slotCloseTab);
    connect(ui.treeView, &QTreeView::doubleClicked, this, &CommGWMgr::treeViewTemplateDoubleClicked);
    connect(ui.treeView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotCustomContextMenu(const QPoint &)));//连接点击右键信号与槽函数
    connect(ui.pushButtonExpand, &QPushButton::clicked, this, &CommGWMgr::slotPushButtonExpand);
    connect(ui.pushButtonShrink, &QPushButton::clicked, this, &CommGWMgr::slotPushButtonShrink);
    connect(ui.actionLog, &QAction::toggled, this, &CommGWMgr::slotActionLog);
    connect(ui.actionTool, &QAction::toggled, this, &CommGWMgr::slotActionTools);
    connect(ui.actionProject, &QAction::toggled, this, &CommGWMgr::slotActionProject);
    connect(ui.actionRestore, &QAction::triggered, this, &CommGWMgr::slotActionRestore);
    connect(ui.actionSysConfig, &QAction::triggered, this, &CommGWMgr::slotActionSysConfig);
    connect(ui.actionDrvCfg, &QAction::triggered, this, &CommGWMgr::slotActionDrvConfig);
    connect(ui.actionAbout, &QAction::triggered, this, &CommGWMgr::slotActionAbout);
    connect(ui.actionUserManual, &QAction::triggered, this, &CommGWMgr::slotActionUserManual);
    connect(ui.actionMonitor, &QAction::triggered, this, &CommGWMgr::slotActionMonitor);
    connect(ui.actionStart, &QAction::triggered, this, &CommGWMgr::slotActionStart);
    connect(ui.actionStop, &QAction::triggered, this, &CommGWMgr::slotActionStop);
    connect(ui.actionReload, &QAction::triggered, this, &CommGWMgr::slotActionReload);
}

void CommGWMgr::loadData()
{
    CPublicData::instance().reLoad();
    if (m_pTreeModel != nullptr)
    {
        for (int i = 0; i < m_pTreeModel->rowCount(); i++)
        {
            QStandardItem *pItem = m_pTreeModel->item(i);

            for (int j = 0; j < pItem->rowCount(); j++)
            {
                QStandardItem *SubpItem = pItem->child(i);
                delete SubpItem;
                SubpItem = nullptr;
            }
            pItem->setRowCount(0);
            delete pItem;
            pItem = nullptr;
        }
        m_pTreeModel->setRowCount(0);
    }
    m_mapItem.clear();
    QStandardItem *pItem = new QStandardItem(QString::fromLocal8Bit("CommGWMgr"));
    pItem->setIcon(QIcon(":/icon/Project.png"));
    m_pTreeModel->setItem(0, pItem);
    QList<CClientData*> listClient = CPublicData::instance().m_listClient;
    for (int i = 0; i < listClient.size(); i++)
    {
        CClientData* pClient = listClient.value(i);
        QString sClientName = pClient->m_sName;
        if (false == pClient->m_bEnabled) sClientName += A2T("(已停用)");
        QStandardItem* pChildItem = new QStandardItem(sClientName);
        pChildItem->setIcon(QIcon(":/icon/Alarm.png"));
        pChildItem->setData(pClient->m_sGuid, 300);
        pItem->setChild(i, pChildItem);
        m_mapItem.insert(pClient->m_sGuid, pChildItem);
        QStandardItem* pState = new QStandardItem(QString::fromLocal8Bit("客户端状态"));
        pState->setData(pClient->m_sGuid, 300);//将树节点的300属性设置成客户端的guid
        pState->setData(0, 301);//将树节点的301属性设置成客户端的guid
        pState->setIcon(QIcon(":/icon/ClientState.png"));
        pChildItem->setChild(0, pState);
        QStandardItem* pPointMg = new QStandardItem(QString::fromLocal8Bit("测点管理"));
        pPointMg->setData(pClient->m_sGuid, 300);//将树节点的300属性设置成客户端的guid
        pPointMg->setData(1, 301);//将树节点的301属性设置成客户端的guid
        pPointMg->setIcon(QIcon(":/icon/Point.png"));
        pChildItem->setChild(1, pPointMg);
    }
    //最后将树完全展开
    ui.treeView->expandAll();
}

void CommGWMgr::initTcpServer()
{
    m_pTcpServer = new CEpollServerMgr;
    m_pTcpServer->setThreadPoolSize(100);
}

bool CommGWMgr::FindWidget(QString WidgetName)
{
    bool bRtn;
    if (m_mapWidget.value(WidgetName))	//该Widget是否被new过
    {
        bRtn = true;
        ui.tabWidget->setCurrentWidget(m_mapWidget.value(WidgetName));
    }
    else
    {
        bRtn = false;
    }
    return bRtn;
}

void CommGWMgr::addWidgetToTab(QWidget* pWidget, QString sTitle, QString sObjName)
{
    ui.tabWidget->addTab(pWidget, sTitle);
    ui.tabWidget->setCurrentWidget(pWidget);
    pWidget->setObjectName(sObjName);
    m_mapWidget.insert(sObjName, pWidget);
}

void CommGWMgr::refushList()
{
    if (m_pTreeModel != nullptr)
    {
        for (int i = 0; i < m_pTreeModel->rowCount(); i++)
        {
            QStandardItem *pItem = m_pTreeModel->item(i);

            for (int j = 0; j < pItem->rowCount(); j++)
            {
                QStandardItem *SubpItem = pItem->child(i);
                delete SubpItem;
                SubpItem = nullptr;
            }
            pItem->setRowCount(0);
            delete pItem;
            pItem = nullptr;
        }
        m_pTreeModel->setRowCount(0);
    }
    m_mapItem.clear();
    QStandardItem *pItem = new QStandardItem(QString::fromLocal8Bit("CommGWMgr"));
    pItem->setIcon(QIcon(":/icon/Project.png"));
    m_pTreeModel->setItem(0, pItem);

    CPublicData::instance().m_pMutex->lock();
    QList<CClientData*> listClient = CPublicData::instance().m_listClient;
    for (int i = 0; i < listClient.size(); i++)
    {
        CClientData* pClient = listClient.value(i);
        QString sClientName = pClient->m_sName;
        if (false == pClient->m_bEnabled) sClientName += A2T("(已停用)");
        QStandardItem* pChildItem = new QStandardItem(sClientName);
        pChildItem->setIcon(QIcon(":/icon/Alarm.png"));
        pChildItem->setData(pClient->m_sGuid, 300);
        pItem->setChild(i, pChildItem);
        m_mapItem.insert(pClient->m_sGuid, pChildItem);
        QStandardItem* pState = new QStandardItem(QString::fromLocal8Bit("客户端状态"));
        pState->setData(pClient->m_sGuid, 300);//将树节点的300属性设置成客户端的guid
        pState->setData(0, 301);//将树节点的301属性设置成客户端的guid
        pState->setIcon(QIcon(":/icon/ClientState.png"));
        pChildItem->setChild(0, pState);
        QStandardItem* pPointMg = new QStandardItem(QString::fromLocal8Bit("测点管理"));
        pPointMg->setData(pClient->m_sGuid, 300);//将树节点的300属性设置成客户端的guid
        pPointMg->setData(1, 301);//将树节点的301属性设置成客户端的guid
        pPointMg->setIcon(QIcon(":/icon/Point.png"));
        pChildItem->setChild(1, pPointMg);
    }
    CPublicData::instance().m_pMutex->unlock();
    //最后将树完全展开
    ui.treeView->expandAll();
}

void CommGWMgr::initSyncBase()
{
    m_pSyncBaseTh=new CSyncBaseTh();
}

void CommGWMgr::startUpJudge()
{
    if (true == CPublicData::instance().m_bAutoStart)
    {
        slotActionStart();
    }
    else
    {
        ui.actionStart->setEnabled(true);
        ui.actionStop->setEnabled(false);
    }
}

void CommGWMgr::slotCloseTab(int index)
{
    //获取要删除的Widget
    QString strName = m_mapWidget.key(ui.tabWidget->widget(index));
    ui.tabWidget->removeTab(index);
    //删除该Widget
    QWidget* pWidget = m_mapWidget.value(strName);
    delete pWidget;
    pWidget = NULL;
    //字典中删除该页面
    m_mapWidget.remove(strName);
}

void CommGWMgr::treeViewTemplateDoubleClicked(const QModelIndex &index)
{
    // 获取点击的节点
    QStandardItem *item = m_pTreeModel->itemFromIndex(index);

    // 判断节点是否是二级节点
    if (item && item->parent() && item->parent()->parent() && item->parent()->parent()->parent()==nullptr)
    {
        QString sGuid = item->data(300).toString();
        int nType= item->data(301).toInt();
        if (CPublicData::instance().m_mapClient.contains(sGuid))
        {
            CClientData* pClient = CPublicData::instance().m_mapClient[sGuid];
            if (nType == 0)//客户端状态
            {
                if (!FindWidget(pClient->m_sGuid + "-0"))
                {
                    CClientState* pClientState = new CClientState(pClient, this);
                    addWidgetToTab(pClientState, QString("[")+pClient->m_sName+QString("]")+A2T("-客户端状态"),pClient->m_sGuid+"-0" );
                }
            }
            else//测点管理
            {
                if (!FindWidget(pClient->m_sGuid + "-1"))
                {
                    CClientPointMng* pClientState = new CClientPointMng(pClient, this);
                    addWidgetToTab(pClientState, QString("[") + pClient->m_sName + QString("]") + A2T("-测点管理"), pClient->m_sGuid + "-1");
                }
            }
        }
    }
}

void CommGWMgr::slotCustomContextMenu(const QPoint &point)
{
    QModelIndex curIndex = ui.treeView->indexAt(point); // 取到当前的节点

    if (!curIndex.isValid())//当前的节点是无效的
    {
        return;
    }
    QStandardItem *item = m_pTreeModel->itemFromIndex(curIndex);
    QString sGuid = item->data(300).toString();
    if (!curIndex.parent().parent().isValid())//客户端节点
    {
        QMenu* pMenu = new QMenu(this);
        pMenu->addAction(new QAction(A2T("添加客户端"), this));
        pMenu->addAction(new QAction(A2T("修改客户端"), this));
        pMenu->addAction(new QAction(A2T("删除客户端"), this));
        QAction* pAction = pMenu->exec(QCursor::pos());
        if (pAction && pAction->text() == A2T("添加客户端"))
        {
            CClientCfgDlg oper;
            oper.m_nType = 0;
            oper.exec();
            refushList();
        }
        else if (pAction && pAction->text() == A2T("修改客户端"))
        {
            if (CPublicData::instance().m_mapClient.contains(sGuid))
            {
                CClientData* pClient = CPublicData::instance().m_mapClient[sGuid];
                CClientCfgDlg oper;
                oper.m_nType = 1;
                oper.setClient(pClient);
                //oper.setData(pClient->m_sName, pClient->m_sIp, pClient->m_nPort, pClient->m_nPointCount);
                oper.exec();
                refushList();
            }
        }
        else if (pAction && pAction->text() == A2T("删除客户端"))
        {
            int nRet = messageBox(3, A2T("是否确定删除此客户端"));
            if (nRet == QMessageBox::Yes)
            {
                CPublicData::instance().m_pMutex->lock();
                if (CPublicData::instance().m_mapClient.contains(sGuid))
                {
                    CClientData* pClient = CPublicData::instance().m_mapClient[sGuid];
                    //首先先将tab页中的界面删掉
                    //删除该Widget
                    if (m_mapWidget.contains(sGuid + "-0"))
                    {
                        QWidget* pWidget = m_mapWidget.value(sGuid + "-0");
                        delete pWidget;
                        pWidget = NULL;
                        //字典中删除该页面
                        m_mapWidget.remove(sGuid + "-0");
                        int nCount = ui.tabWidget->count();
                        for (int i = 0; i < nCount; i++)
                        {
                            if (QString("[") + pClient->m_sName + QString("]") + A2T("-测点管理") == ui.tabWidget->tabText(i))
                            {
                                ui.tabWidget->removeTab(i);
                                break;
                            }
                        }
                    }
                    if (m_mapWidget.contains(sGuid + "-1"))
                    {
                        QWidget* pWidget = m_mapWidget.value(sGuid + "-1");
                        delete pWidget;
                        pWidget = NULL;
                        //字典中删除该页面
                        m_mapWidget.remove(sGuid + "-1");
                        int nCount = ui.tabWidget->count();
                        for (int i = 0; i < nCount; i++)
                        {
                            if (QString("[") + pClient->m_sName + QString("]") + A2T("-客户端状态") == ui.tabWidget->tabText(i))
                            {
                                ui.tabWidget->removeTab(i);
                                break;
                            }
                        }
                    }
                    delete pClient;
                    pClient = nullptr;
                }
                CPublicData::instance().m_mapClient.remove(sGuid);
                CPublicData::instance().m_pMutex->unlock();
                refushList();
            }
        }
    }
}

void CommGWMgr::slotPushButtonExpand()
{
    ui.treeView->expandAll();
}

void CommGWMgr::slotPushButtonShrink()
{
    ui.treeView->collapseAll();
}

void CommGWMgr::slotDataFlush()
{
    CPublicData::instance().m_pMutex->lock();
    for (QMap<QString, CClientData*>::iterator itor = CPublicData::instance().m_mapClient.begin(); itor != CPublicData::instance().m_mapClient.end(); itor++)
    {
        CClientData* pClient = itor.value();
        pClient->m_pMutex->lock();
        bool bState = pClient->m_bState;
        QString sGuid = pClient->m_sGuid;
        if (m_mapItem.contains(sGuid))
        {
            if (bState)
            {
                m_mapItem[sGuid]->setIcon(QIcon(":/icon/Green.png"));
            }
            else
            {
                m_mapItem[sGuid]->setIcon(QIcon(":/icon/Alarm.png"));
            }
            pClient->m_pMutex->unlock();
        }
        else
        {
            pClient->m_pMutex->unlock();
        }
    }
    CPublicData::instance().m_pMutex->unlock();
}

void CommGWMgr::slotActionStart()
{
    if(m_pSyncBaseTh != nullptr)
    {
        m_pSyncBaseTh->threadStart();
    }
    else
    {
        m_pSyncBaseTh = new CSyncBaseTh();
        m_pSyncBaseTh->threadStart();
    }
    if (m_pTcpServer == nullptr)
        initTcpServer();

    bool bRtn = m_pTcpServer->startServer(CPublicData::instance().m_stServerCfg.m_nPort);
    if (bRtn == false)
    {
        m_pSyncBaseTh->threadStop();
        return;
    }

    ui.actionStart->setEnabled(false);
    ui.actionStop->setEnabled(true);
}

void CommGWMgr::slotActionStop()
{
    if (m_pTcpServer)
    {
        m_pTcpServer->stopServer();
    }
    if(m_pSyncBaseTh)
    {
        m_pSyncBaseTh->threadStop();
    }
    ui.actionStart->setEnabled(true);
    ui.actionStop->setEnabled(false);
}

void CommGWMgr::slotActionReload()
{
    int ret = QMessageBox::information(this, A2T("提示"), A2T("是否确认重载?"), QMessageBox::Yes, QMessageBox::No);
    if (ret == QMessageBox::No)
    {
        return;
    }
    slotActionStop();
    loadData();
    slotActionStart();
}

void CommGWMgr::slotActionLog(bool bChecked)
{
    if (bChecked)
    {
        ui.dockWidgetLog->show();
    }
    else
    {
        ui.dockWidgetLog->hide();
    }
}

void CommGWMgr::slotActionTools(bool bChecked)
{
    if (bChecked)
    {
        ui.mainToolBar->show();
    }
    else
    {
        ui.mainToolBar->hide();
    }
}

void CommGWMgr::slotActionProject(bool bChecked)
{
    if (bChecked)
    {
        ui.dockWidgetPro->show();
    }
    else
    {
        ui.dockWidgetPro->hide();
    }
}

void CommGWMgr::slotActionRestore()
{
    int ret = QMessageBox::information(this, A2T("提示"), A2T("是否确认备份工程?"), QMessageBox::Yes, QMessageBox::No);
    if (ret == QMessageBox::No)
    {
        return;
    }
    QString sIniPath = QCoreApplication::applicationDirPath() + "/config/config.ini";
    QSettings settings(sIniPath, QSettings::IniFormat);
    settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
    // 设置主配置
    settings.beginGroup("Main");
    settings.setValue("IP",CPublicData::instance().m_stServerCfg.m_sServerIp);
    settings.setValue("Port", CPublicData::instance().m_stServerCfg.m_nPort);
    settings.setValue("ClientMaxNum", CPublicData::instance().m_stServerCfg.m_nClientMax);
    settings.setValue("ClientNum", CPublicData::instance().m_mapClient.size());
    settings.endGroup();

    settings.beginGroup("SyncBase");
    settings.setValue("IP",CPublicData::instance().m_stSyncBaseCfg.m_sIp);
    settings.setValue("Port", CPublicData::instance().m_stSyncBaseCfg.m_nPort);
    settings.setValue("User", CPublicData::instance().m_stSyncBaseCfg.m_sUser);
    settings.setValue("PassWd", CPublicData::instance().m_stSyncBaseCfg.m_sPassWd);
    settings.setValue("DbName", CPublicData::instance().m_stSyncBaseCfg.m_sDbName);
    settings.endGroup();

    int n = 0;
    for (QMap<QString, CClientData*>::iterator itor = CPublicData::instance().m_mapClient.begin(); itor != CPublicData::instance().m_mapClient.end(); itor++)
    {
        CClientData* pClient = itor.value();
        settings.beginGroup(QString("Client%1").arg(n));
        settings.setValue("ClientName", pClient->m_sName);
        settings.setValue("IP", pClient->m_sIp);
        settings.setValue("Port", pClient->m_nPort);
        settings.endGroup();
        n++;
    }

    QMessageBox::information(this, A2T("提示"), A2T("导出成功"), QMessageBox::Yes, QMessageBox::No);
}

void CommGWMgr::slotActionBackup()
{

}

void CommGWMgr::slotActionSysConfig()
{
    CSysConfig oper;
    oper.exec();
}

void CommGWMgr::slotActionDrvConfig()
{
    CDrvSyncBaseCfg oper;
    oper.exec();
}

void CommGWMgr::slotActionAbout()
{
    CAboutDlg oper;
    oper.exec();
}

void CommGWMgr::slotActionUserManual()
{
    // 获取文件路径
    QString sFilePath = "";
#ifdef Q_OS_WIN
    sFilePath=QCoreApplication::applicationDirPath() + "/Help/Help.docx";
#elif defined(Q_OS_LINUX)
    sFilePath=QCoreApplication::applicationDirPath() + "/Help/Help.odt";
#endif
   // 检查文件是否存在
   if (QFile::exists(sFilePath))
   {
       // 在 Windows 上，Qt 会自动处理路径分隔符问题
       // Linux 上使用xdg-open来打开文件
       QString command;
#ifdef Q_OS_WIN
       // Windows 上使用 ShellExecuteW
       command = "explorer \"" + sFilePath + "\"";
#elif defined(Q_OS_LINUX)
       // Linux 上使用 xdg-open
       command = "xdg-open \"" + sFilePath + "\"";
#endif
       // 执行打开文件的命令
       QProcess::startDetached(command);
   }
   else
   {
       // 文件不存在时显示消息框
       QMessageBox::information(nullptr, "提示", "未找到软件使用手册");
   }
}

void CommGWMgr::slotActionMonitor()
{
    CTagMobitorDlg oper;
    oper.exec();
}

